#include <stddef.h>
#include <string.h>
#include <stdint.h>
#include <Utility.h>

#include "FreeRTOS.h"
#include "timers.h"

#include <phApp_Init.h>
#include <phNfcLib_Int.h>
#include <phNfcLib_Initialization.h>
#include "BSP.h"
#include "Reader.h"
#include "log/log2.h"

#include "config/config2.h"
#include <Reader/Reader.h>
#include <Reader/ReaderDesfire2.h>

/*===================================================================================*/

#define AID_ISSUE		0xCF0001
#define AID_DATA		0xCF0002

// #define KID_KFR0		0x01
// #define KID_KFR			0x02
// #define KID_KFM			0x03

#define KEY_NO_KFR0		0x01		//工厂默认读密钥号（卡）
#define KEY_NO_KUR		0x01		//用户读密钥号（卡）
#define	KEY_NO_KMR		0x01		//厂商读密钥号（卡）

#define FID_MANU_INFO		0x00	//厂商信息文件ID
#define FID_USER_INFO		0x00	//用户信息文件ID
#define FID_APPLE_WALLET	0x01	//苹果钱包文件ID
#define FID_GOOGLE_WALLET	0x02	//谷歌钱包文件ID
#define FID_LEAF			0x03	//LEAF卡文件ID
#define FID_KEY_DATA		0x10	//密钥数据文件ID

// static const uint8_t key_kfr0[16] = 
// 	{	
// 		0x5A,0x4B,0x52,0x65,
// 		0x61,0x64,0x65,0x72,
// 		0x4D,0x33,0x35,0x36,
// 		0x22,0x22,0x33,0x33
// 	};
// static const uint8_t key_kfr[16] = {0x5A,0x4B,0x52,0x65,0x61,0x64,0x65,0x72,0x4D,0x33,0x35,0x36,0x22,0x22,0x33,0x33};
// static const uint8_t key_kfm[16] = {0x5A,0x4B,0x52,0x65,0x61,0x64,0x65,0x72,0x4D,0x33,0x35,0x36,0x88,0x88,0x99,0x99};
// static const uint8_t key_default[16] = {0};

// static const uint8_t key_kur[16] = {
// 	0x66,0x66,0x66,0x66,
// 	0x66,0x66,0x66,0x66,
// 	0x66,0x66,0x66,0x66,
// 	0x66,0x66,0x66,0x66
// };

// static const uint8_t key_kum[16] = {
// 	0x77,0x77,0x77,0x77,
// 	0x77,0x77,0x77,0x77,
// 	0x77,0x77,0x77,0x77,
// 	0x77,0x77,0x77,0x77
// };
// typedef enum {
// 	KEY_T_3DES = 1,
// 	KEY_T_AES128 = 2,
// 	KEY_T_3K3DES = 3,
// 	KEY_T_AES192 = 4,
// 	KEY_T_AES256 = 5,
// 	KEY_T_MAX,
// }key_type_t;
typedef enum {
	CARD_T_USER = 0,		//用户配置卡
	CARD_T_CUSTOM = 1,		//客户化卡
	CARD_T_MANU = 2,		//厂商配置卡
	CARD_T_INIT = 3,		//初始化卡
}card_type_t;

#pragma pack(1)

//公共文件
typedef struct {
	uint16_t version;	//版本
	uint32_t time;		//写卡时间
	uint8_t type;		//类型：0 - 用户配置卡。1 - 授权卡。2 - 厂商配置卡。3 - 激活卡。	
	uint8_t isser_code[16];//厂商信息
	uint8_t cmac[8];
}card_info_t;
// typedef struct {
// 	uint8_t key_id;
// 	uint8_t key_ver;
// 	uint8_t key_type;
// 	uint8_t key_val[32];
// }key_t;
//配置卡密钥
typedef struct {
	uint16_t version;	//版本
	uint32_t time;		//写卡时间
	uint8_t isser_code[16];//验证码
	uint8_t key_num;
	key_t keys[8];
	uint8_t cmac[8];
}cfg_keys_t;
//密钥数据
typedef struct {
	uint16_t version;	//版本	
	uint8_t key_num;
	key_t keys[8];
	uint8_t cmac[8];
}key_data_t;

#pragma pack()

typedef struct {
	card_info_t info;				//发行信息
	card_info_t user;				//用户信息
	// cfg_keys_t cfg_keys;		
	key_data_t key_datas;			//密钥数据
	// cfg_apple_wallet_t cfg_apple;	//苹果钱包配置
	// cfg_google_wallet_t cfg_google;	//谷歌钱包配置
	uint8_t uid[8];
	uint8_t ulen;
}cfg_card_t;

static void reader_pr_cfg_info(const card_info_t* card_info){
	LOG2_DBG("version: %X", card_info->version);
	LOG2_DBG("time: %u", card_info->time);
	LOG2_DBG("type: %u", card_info->type);
	LOG2_BUF_DBG("isser_code", card_info->isser_code, sizeof(card_info->isser_code));
	LOG2_BUF_DBG("cmac", card_info->cmac, sizeof(card_info->cmac));
}

static void reader_pr_cfg_keys(const cfg_keys_t* cfg_keys){
	LOG2_DBG("version: %X", cfg_keys->version);
	LOG2_DBG("time: %u", cfg_keys->time);
	LOG2_BUF_DBG("isser_code", cfg_keys->isser_code, sizeof(cfg_keys->isser_code));
	LOG2_DBG("key_num: %u", cfg_keys->key_num);
	for(int i = 0; i < cfg_keys->key_num; i++){
		LOG2_DBG("key_id: %u", cfg_keys->keys[i].id);
		LOG2_DBG("key_ver: %u", cfg_keys->keys[i].ver);
		LOG2_DBG("key_type: %u", cfg_keys->keys[i].type);
		LOG2_BUF_DBG("key_val", cfg_keys->keys[i].data, sizeof(cfg_keys->keys[i].data));
	}
	LOG2_BUF_DBG("cmac", cfg_keys->cmac, sizeof(cfg_keys->cmac));
}

static void reader_pr_key_data(const key_data_t* key_data){
	LOG2_DBG("version: %X", key_data->version);	
	LOG2_DBG("key_num: %u", key_data->key_num);
	for(int i = 0; i < key_data->key_num; i++){
		LOG2_DBG("key_id: %u", key_data->keys[i].id);
		LOG2_DBG("key_ver: %u", key_data->keys[i].ver);
		LOG2_DBG("key_type: %u", key_data->keys[i].type);
		LOG2_BUF_DBG("key_val", key_data->keys[i].data, sizeof(key_data->keys[i].data));
	}
	LOG2_BUF_DBG("cmac", key_data->cmac, sizeof(key_data->cmac));
}

// static void reader_pr_cfg_google_wallet(const cfg_google_wallet_t* cfg_google){
// 	// LOG2_DBG("version: %X", cfg_google->version);
// 	// LOG2_DBG("time: %u", cfg_google->time);
// 	// LOG2_DBG("key_num: %u", cfg_google->key_num);
// 	// for(int i = 0; i < cfg_google->key_num; i++){
// 	// 	LOG2_DBG("key_id: %u", cfg_google->keys[i].key_id);
// 	// 	LOG2_DBG("key_ver: %u", cfg_google->keys[i].key_ver);
// 	// 	LOG2_DBG("key_type: %u", cfg_google->keys[i].key_type);
// 	// 	LOG2_BUF_DBG("key_val", cfg_google->keys[i].key_val, sizeof(cfg_google->keys[i].key_val));
// 	// }
// 	// LOG2_BUF_DBG("cmac", cfg_google->cmac, sizeof(cfg_google->cmac));
// }

// static void reader_pr_cfg_apple_wallet(const cfg_apple_wallet_t* cfg_apple){
// 	// LOG2_DBG("version: %X", cfg_apple->version);
// 	// LOG2_DBG("time: %u", cfg_apple->time);
// 	// LOG2_DBG("key_num: %u", cfg_apple->key_num);
// 	// for(int i = 0; i < cfg_apple->key_num; i++){
// 	// 	LOG2_DBG("key_id: %u", cfg_apple->keys[i].key_id);
// 	// 	LOG2_DBG("key_ver: %u", cfg_apple->keys[i].key_ver);
// 	// 	LOG2_DBG("key_type: %u", cfg_apple->keys[i].key_type);
// 	// 	LOG2_BUF_DBG("key_val", cfg_apple->keys[i].key_val, sizeof(cfg_apple->keys[i].key_val));
// 	// }
// 	// LOG2_BUF_DBG("cmac", cfg_apple->cmac, sizeof(cfg_apple->cmac));
// }

static void reader_pr_cfg_card(const cfg_card_t* cfg_card){
	reader_pr_cfg_info(&cfg_card->info);
	// reader_pr_cfg_keys(&cfg_card->cfg_keys);
	reader_pr_key_data(&cfg_card->key_datas);
	// reader_pr_cfg_google_wallet(&cfg_card->cfg_google);
	// reader_pr_cfg_apple_wallet(&cfg_card->cfg_apple);
}

static int reader_cfg_select_app(uint32_t aid){
	int ret = Reader_MFDF_SelectApplication(PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t*)&aid, NULL);
	if(ret){
		LOG2_ERR("select app(%06X) fail: %04X", aid, ret);
	}
	return ret;
}

static int reader_cfg_load_key(uint8_t key_no, uint8_t ver, uint8_t key_type, uint8_t *key_data){
	void* key_store = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
	phKeyStore_FormatKeyEntry(key_store, key_no, key_type);
	phKeyStore_SetKeyAtPos(key_store, key_no, 0, key_type, key_data, ver);
	return 0;
}

static int reader_cfg_auth(uint8_t key_no, uint8_t ver, uint8_t card_key_no){
	int ret = Reader_MFDF_AuthenticateAES(PHAL_MFDFEVX_NO_DIVERSIFICATION, key_no, ver, card_key_no, NULL, 0);		
	if(ret){
		LOG2_ERR("auth fail: %04X", ret);
	}
	return ret;
}

static int reader_cfg_auth_div(uint8_t key_no, uint8_t ver, uint8_t card_key_no, uint8_t* div, uint8_t div_len){
	int ret = Reader_MFDF_AuthenticateAES(PHAL_MFDFEVX_DIV_METHOD_CMAC, key_no, ver, card_key_no, div, div_len);		
	if(ret){
		LOG2_ERR("auth fail: %04X", ret);
	}
	return ret;
}

#if 0
static int reader_cfg_auth(uint8_t key_no, uint8_t ver, uint8_t card_key_no){
	int ret = Reader_MFDF_Authenticate(PHAL_MFDFEVX_NO_DIVERSIFICATION, key_no, ver, card_key_no, NULL, 0);		
	if(ret){
		LOG2_ERR("auth fail: %04X", ret);
	}
	return ret;
}
#endif 

//生成DIV
static void reader_cfg_gen_div(uint8_t uid[], uint32_t aid, uint8_t div[16]){
	uint8_t buf[16];
	memset(buf, 0, sizeof(buf));
	memcpy(buf, uid, 7);
	buf[8] = aid >> 16;
	buf[9] = aid >> 8;
	buf[10] = aid;
	memcpy(div, buf, 16);
}

//分散密钥
static void reader_cfg_div_key(uint8_t* skey, uint8_t* div, uint8_t dlen, uint8_t * dkey){
	LOG2_BUF_DBG("skey", skey, 16);
	LOG2_BUF_DBG("div", div, dlen);
	void * pDataParams = phNfcLib_GetDataParams_Extended(PH_COMP_CRYPTOSYM, PH_NFCLIB_COMP_CRYPTOSYM_TYPE_DIVERSIFY);
	phStatus_t status = phCryptoSym_DiversifyDirectKey(
		pDataParams,
		PHAL_MFDFEVX_DIV_METHOD_CMAC,
		skey,
		PH_KEYSTORE_KEY_TYPE_AES128,
		div,
		dlen,
		dkey
		);
	LOG2_BUF_DBG("dkey", dkey, 16);	
}

//实现认证
static int reader_cfg_auth_card(uint8_t kid, uint8_t card_key_no){
	//认证密钥
	int ret;
	key_t key;
	uint8_t keyNo = 1;
	uint8_t ver = 0;
	//获取密钥
	if(config_get_key(kid, &key)){
		return -1;
	}
	//加载密钥
	ret = reader_cfg_load_key(keyNo, ver, PH_KEYSTORE_KEY_TYPE_AES128, (uint8_t *)key.data);
	//认证
	ret = reader_cfg_auth(keyNo, ver, card_key_no);
	if(ret){
		//默认密钥错误，不是配置卡
		return -2;
	}
	return 0;
}

static int reader_cfg_auth_card_div(uint8_t kid, uint8_t card_key_no, uint8_t* div, uint8_t dlen){
	//认证密钥
	int ret;
	key_t key;
	uint8_t keyNo = 1;
	uint8_t ver = 0;
	//获取密钥
	if(config_get_key(kid, &key)){
		return -1;
	}
	//分散密钥
	 LOG2_BUF_DBG("key", key.data, 16);
	 LOG2_BUF_DBG("div", div, dlen);
	//加载密钥
	ret = reader_cfg_load_key(keyNo, ver, PH_KEYSTORE_KEY_TYPE_AES128, (uint8_t *)key.data);
	//认证
	ret = reader_cfg_auth_div(keyNo, ver, card_key_no, div, dlen);
	if(ret){
		//默认密钥错误，不是配置卡
		return -2;
	}
	return 0;
}


int reader_cfg_clac_mac(const uint8_t *keys, uint8_t* data, uint16_t len, uint8_t* mac){
	void * pDataparam = phNfcLib_GetDataParams_Extended(PH_COMP_CRYPTOSYM, PH_NFCLIB_COMP_CRYPTOSYM_TYPE_ENC);
	phStatus_t  status = 0;

	status = phCryptoSym_LoadKeyDirect(pDataparam, keys, PH_KEYSTORE_KEY_TYPE_AES128);
	if(status){
		LOG2_ERR("phCryptoSym_LoadKeyDirect fail: %04X", status);
		return status;		
	}

	uint8_t aIV[PH_CRYPTOSYM_AES_BLOCK_SIZE];
    /* Load zero to IV */
    (void)memset(aIV, 0x00, PH_CRYPTOSYM_AES_BLOCK_SIZE);

    /* Load the IV. */
    status = phCryptoSym_LoadIv(
        pDataparam,
        aIV,
        PH_CRYPTOSYM_AES_BLOCK_SIZE);
    if(status){
		LOG2_ERR("phCryptoSym_LoadIv fail: %04X", status);
		return status;
	}
	
	uint8_t len_mac = 0;
	status = phCryptoSym_CalculateMac(pDataparam, PH_EXCHANGE_DEFAULT, data, len, mac, &len_mac);
	if(status){
		LOG2_ERR("phCryptoSym_CalculateMac fail: %04X", status);
		return status;	
	}
	return status;
}

static int reader_cfg_check_mac(const uint8_t *keys, uint8_t* data, uint16_t len){
	uint8_t mac_calc[16];
	uint16_t dlen = len - 8;
	uint8_t* mac = data + dlen;
	int ret = reader_cfg_clac_mac(keys, data, len, mac_calc);
	if(ret){
		return ret;
	}
	if(memcmp(mac_calc, mac, 8) != 0){
		LOG2_ERR("mac check fail");
		LOG2_BUF_ERR("mac", mac, 8);
		LOG2_BUF_ERR("mac_calc", mac_calc, 8);
		return -1;
	}
	return 0;
}

/*
计算mac
参数：
	kid：密钥ID
	data：数据
	len：数据长度
	mac：指向校验MAC的指针
返回值：
	0：成功
	其他：失败
*/

static int reader_cfg_check_mac3(uint8_t kid, uint8_t* data, uint16_t dlen, uint8_t* mac){
	uint8_t mac_calc[16];
	key_t key;

	//获取密钥
	if(config_get_key(kid, &key)){
		return -1;
	}
	int ret = reader_cfg_clac_mac(key.data, data, dlen, mac_calc);
	if(ret){
		return ret;
	}
	if(memcmp(mac_calc, mac, 8) != 0){
		LOG2_ERR("mac check fail");
		LOG2_BUF_ERR("mac", mac, 8);
		LOG2_BUF_ERR("mac_calc", mac_calc, 8);
		return -1;
	}
	return 0;
}

static int reader_cfg_check_mac2(uint8_t kid, uint8_t* data, uint16_t len){
	uint8_t mac_calc[16];
	key_t key;
	uint16_t dlen = len - 8;
	uint8_t* mac = data + dlen;
	//获取密钥
	if(config_get_key(kid, &key)){
		return -1;
	}
	int ret = reader_cfg_clac_mac(key.data, data, dlen, mac_calc);
	if(ret){
		return ret;
	}
	if(memcmp(mac_calc, mac, 8) != 0){
		LOG2_ERR("mac check fail");
		LOG2_BUF_ERR("mac", mac, 8);
		LOG2_BUF_ERR("mac_calc", mac_calc, 8);
		return -1;
	}
	return 0;
}

//分散密钥后，检测mac
static int reader_cfg_check_mac_div(uint8_t kid, uint8_t div[16], uint8_t* data, uint16_t dlen, uint8_t* mac){
	uint8_t mac_calc[16];
	key_t key;

	//获取密钥
	if(config_get_key(kid, &key)){
		return -1;
	}

	reader_cfg_div_key(key.data, div, 16, key.data);
	int ret = reader_cfg_clac_mac(key.data, data, dlen, mac_calc);
	if(ret){
		return ret;
	}
	if(memcmp(mac_calc, mac, 8) != 0){
		LOG2_ERR("mac check fail");
		LOG2_BUF_ERR("mac", mac, 8);
		LOG2_BUF_ERR("mac_calc", mac_calc, 8);
		return -1;
	}
	return 0;
}


static int reader_cfg_read_data(uint8_t bFileNo, void *data, uint16_t dlen){
	uint8_t offset[3] = {0x00};
	uint8_t length[3] = {(uint8_t)dlen, (uint8_t)(dlen >> 8), 0x00};
	uint8_t *pdata;
	uint16_t rlen = 0;
	int ret = Reader_MFDF_ReadData(PHAL_MFDFEVX_COMMUNICATION_ENC, PHAL_MFDFEVX_APPLICATION_CHAINING, bFileNo, offset, length, &pdata, &rlen);
	if(ret){
		LOG2_ERR("Reader_MFDF_ReadData fail: %04X", ret);
		return ret;
	}
	if(rlen != dlen){
		LOG2_ERR("rxlen=%d, len=%d", rlen, dlen);
		return -1;
	}

	memcpy(data, pdata, dlen);
	return 0;
}

static int reader_cfg_read_data2(uint8_t bFileNo, uint16_t off, void *data, uint16_t dlen){
	uint8_t offset[3] = {(uint8_t)off, (uint8_t)(off >> 8), 0x00};
	uint8_t length[3] = {(uint8_t)dlen, (uint8_t)(dlen >> 8), 0x00};
	uint8_t *pdata;
	uint16_t rlen = 0;
	int ret = Reader_MFDF_ReadData(PHAL_MFDFEVX_COMMUNICATION_ENC, PHAL_MFDFEVX_APPLICATION_CHAINING, bFileNo, offset, length, &pdata, &rlen);
	if(ret){
		LOG2_ERR("Reader_MFDF_ReadData fail: %04X", ret);
		return ret;
	}
	if(rlen != dlen){
		LOG2_ERR("rxlen=%d, len=%d", rlen, dlen);
		return -1;
	}

	memcpy(data, pdata, dlen);
	return 0;
}

//读取密钥数据文件
static int reader_cfg_read_key_data(key_data_t* key_data){
	uint16_t offset = 0;
	//读取版本和密钥数
	int ret = reader_cfg_read_data2(FID_KEY_DATA, offset, (void *)key_data, 3);
	if(ret){
		LOG2_ERR("reader_cfg_read_data fail: %d", ret);
		return ret;	
	}
	offset += 3;
	//读取密钥数据
	ret = reader_cfg_read_data2(FID_KEY_DATA, offset, (void *)&key_data->keys, key_data->key_num * sizeof(key_t));
	if(ret){
		LOG2_ERR("reader_cfg_read_data fail: %d", ret);
		return ret;
	}
	offset += key_data->key_num * sizeof(key_t);
	//读取MAC
	ret = reader_cfg_read_data2(FID_KEY_DATA, offset, (void *)key_data->cmac, 8);
	if(ret){
		LOG2_ERR("reader_cfg_read_data fail: %d", ret);
		return ret;
	}
	return 0;
}

static int reader_cfg_read_data_and_check(const uint8_t *keys, uint8_t bFileNo, void *data, uint16_t dlen){
	//读取数据
	int ret = reader_cfg_read_data(bFileNo, data, dlen);
	if(ret){
		// LOG2_ERR("reader_cfg_read_data fail: %d", ret);
		return ret;
	}	
	//校验MAC
	if(reader_cfg_check_mac(keys, data, dlen)){
		LOG2_ERR("mac check fail");
		return -2;
	}
	return 0;
}
/**
 * @brief 检查配置卡信息的有效性
 * 
 * @param card_info 指向存储卡信息的结构体的指针
 * @return int 返回0表示成功，非0表示失败
 */
static int reader_cfg_check_card_info(cfg_card_t* cfg_card){
    card_info_t* card_info = &cfg_card->info;
    int ret; // 用于存储函数返回值
    key_t key; // 用于存储密钥信息的结构体
	uint8_t kid;
    // 根据卡的类型获取相应的密钥
    switch (card_info->type) 
    {
    case CARD_T_USER: kid = KID_KUM; break;
    case CARD_T_CUSTOM: kid = KID_KCM; break;
    case CARD_T_MANU: kid = KID_KMM; break;
    case CARD_T_INIT: kid = KID_KFM; break;    
    default:
        LOG2_ERR("card_type error: %d", card_info->type); // 记录错误日志，卡类型错误
        return -1;
    }

    // 检查MAC（消息认证码）是否有效    
    uint8_t *data = (uint8_t *)card_info;
	uint16_t dlen = sizeof(card_info_t) - 8;
	uint8_t* mac = data + dlen;
    uint8_t div[16] = {0};

	reader_cfg_gen_div(cfg_card->uid, AID_ISSUE, div);
    if(reader_cfg_check_mac_div(kid, div, (uint8_t *)card_info, dlen, mac)){
        LOG2_ERR("mac check fail"); // 记录错误日志，MAC检查失败
        return -4; // 返回错误码-4    
    }

    return 0; // 返回成功码0
}

/**
 * @brief 读取配置卡信息
 * 
 * @param card_info 指向存储卡信息的结构体的指针
 * @return int 返回0表示成功，非0表示失败
 */
static int reader_read_cfg_card_info(cfg_card_t* cfg_card){
    int ret;
    uint8_t keyNo = 1;
    uint8_t ver = 0;
	card_info_t* card_info = &cfg_card->info;
    //选择应用
    ret = reader_cfg_select_app(AID_ISSUE);
    if(ret){
        return 1;
    }
    //认证密钥
    ret = reader_cfg_auth_card(KID_KFR0, KEY_NO_KFR0);
    if(ret){
        return 1;
    }
	//读取数据
    ret = reader_cfg_read_data(FID_MANU_INFO, card_info, sizeof(card_info_t));
    if(ret){
        return 3;
    }
    ret = reader_cfg_check_card_info(cfg_card);
    if(ret){
        return 4;
    }
    return 0;
}

static int reader_read_card_data(uint8_t kid, cfg_card_t* cfg_card){
    int ret;

    //选择应用
    ret = reader_cfg_select_app(AID_DATA);
    if(ret){
        return 2;
    }
	//认证密钥    
    uint8_t div[16] = {0};

	reader_cfg_gen_div(cfg_card->uid, AID_DATA, div);
	ret = reader_cfg_auth_card_div(kid, KEY_NO_KUR, div, 16);
    if(ret){
        return 2;
    }

    //读取验证码
    ret = reader_cfg_read_data(FID_USER_INFO, &cfg_card->user, sizeof(card_info_t));
    if(ret){
        return 3;
    }

    //读密钥数据
	ret = reader_cfg_read_key_data(&cfg_card->key_datas);
    if(ret){
        return 5;
    }
    // //校验MAC
	key_data_t* key_data = &cfg_card->key_datas;    
	reader_cfg_gen_div(cfg_card->uid, AID_DATA, div);
	ret = reader_cfg_check_mac_div(kid, div, (uint8_t *)key_data, key_data->key_num * sizeof(key_t) + 3, key_data->cmac);
    if(ret){
        return 6;
    }
    return 0;
}

static int reader_read_cfg_card_data(cfg_card_t* cfg_card){
    switch (cfg_card->info.type)
    {
    case CARD_T_USER:	return reader_read_card_data(KID_KUR, cfg_card);
    case CARD_T_CUSTOM:	return reader_read_card_data(KID_KCR, cfg_card);
    case CARD_T_MANU:	return reader_read_card_data(KID_KMR, cfg_card);
    case CARD_T_INIT:	return reader_read_card_data(KID_KFR, cfg_card);
    default:
        LOG2_ERR("unknow card type: %d", cfg_card->info.type);
        break;
    }

    return -1;
}

//保存配置卡数据
static int reader_cfg_save_card_data(cfg_card_t* cfg_card){
    int ret = config_update(cfg_card->key_datas.keys, cfg_card->key_datas.key_num);
	if(ret){
		return ret;
	}

	//INIT卡，CUSTOM卡，清除苹果和Google密钥
	if(cfg_card->info.type == CARD_T_INIT 
		|| cfg_card->info.type == CARD_T_CUSTOM){
		key_t key = {0};
		config_set_key(KID_APPLE_PRIV, &key);
		config_set_key(KID_APPLE_CRED, &key);
		config_set_key(KID_GOOGLE, &key);
	}
	//INIT卡，清除用户密钥
	if(cfg_card->info.type == CARD_T_INIT){
		key_t key = {0};
		config_set_key(KID_KUR, &key);
		config_set_key(KID_KUM, &key);
	}
	//CUSTOM卡，清除厂商密钥
	if(cfg_card->info.type == CARD_T_CUSTOM){
		key_t key = {0};
		config_set_key(KID_KMR, &key);
		config_set_key(KID_KMM, &key);
	}
	//保存配置
    return config_sync();
}

static int cfg_tag_live;
static SimpleTag_T cfg_tag;
//配置卡定时器
static TimerHandle_t reader_cfg_timer;

//检测tag是否是新tag
static int reader_cfg_is_new_tag(SimpleTag_T* tag){
	if(cfg_tag_live == 0){
		return 1;
	}
	if(tag->ulen != cfg_tag.ulen){
		return 1;	
	}
	if(memcmp(tag->uid, cfg_tag.uid, tag->ulen) != 0){
		return 1;
	}
	return 0;
}

/**
 * @brief 配置wavelynx卡
 * 
 * @return int 返回0表示成功，非0表示失败
 */
int reader_wavelynx_config2(SimpleTag_T* tag){
    cfg_card_t cfg_card;
	if(!reader_cfg_is_new_tag(tag)){
		cfg_tag_live = 20;
		return 0;
	}
	memset(&cfg_card, 0, sizeof(cfg_card));
	memcpy(cfg_card.uid, tag->uid, tag->ulen);
	cfg_card.ulen = tag->ulen;
    int ret = reader_read_cfg_card_info(&cfg_card);
    if(ret){
        return ret;
    }
    reader_pr_cfg_info(&cfg_card.info);
    ret = reader_read_cfg_card_data(&cfg_card);
    if(ret){
        return ret;
    }
    //保存数据
    ret = reader_cfg_save_card_data(&cfg_card);
	if(ret){
		return ret;
	}
	//更新tag
	memcpy(&cfg_tag, tag, sizeof(SimpleTag_T));
	cfg_tag_live = 20;
    return 0;
}


//配置卡定时器回调
static void reader_cfg_tick(TimerHandle_t xTimer){
	if(cfg_tag_live > 0){
		cfg_tag_live--;
		if(cfg_tag_live == 0){
			//配置卡超时
			memset(&cfg_tag, 0, sizeof(cfg_tag));
		}
	}
}

void reader_wavelynx_config_init(void){
	reader_cfg_timer = xTimerCreate("cfg_timer", pdMS_TO_TICKS(100), pdTRUE, NULL, reader_cfg_tick);
	xTimerStart(reader_cfg_timer, portMAX_DELAY);
}

